package com.ctshk.rpc.season.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SeasonType;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.scenic.dto.ScenicPriceDTO;
import com.ctshk.rpc.scenic.service.IScenicReservationService;
import com.ctshk.rpc.season.dto.PackageProductCostDTO;
import com.ctshk.rpc.season.dto.SeasonFixedProductPackageScenicDTO;
import com.ctshk.rpc.season.entity.SeasonFixedProductPackageScenic;
import com.ctshk.rpc.season.mapper.SeasonFixedProductPackageScenicMapper;
import com.ctshk.rpc.season.req.PassengerReq;
import com.ctshk.rpc.season.req.SeasonFixedProductPackageScenicReq;
import com.ctshk.rpc.season.req.UpdatePackageProductReq;
import com.ctshk.rpc.season.service.ISeasonFixedProductPackageScenicService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 套票-固定套票单项产品打包-景点门票表 服务实现类
 * </p>
 *
 * @author 杨林
 * @since 2021-03-09
 */
@Slf4j
@DubboService
public class SeasonFixedProductPackageScenicServiceImpl extends ServiceImpl<SeasonFixedProductPackageScenicMapper, SeasonFixedProductPackageScenic> implements ISeasonFixedProductPackageScenicService {

    @Autowired
    private SeasonFixedProductPackageScenicMapper seasonFixedProductPackageScenicMapper;

    @DubboReference
    private IScenicReservationService scenicReservationService;


    /* @MethodName: 获取景点门票成本信息
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/26 16:47
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PackageProductCostDTO getScenicProductPrice(Long productId, LocalDate departDate, Long userId, Integer channelType, Long attrId1, Long attrId2) {
        PackageProductCostDTO cost = new PackageProductCostDTO();
        try {
            log.info(String.format("调用景点门票服务获取价格发生异常入参,channelType:%s,productId:%s ,departDate:%s ,userId:%s ,attrId1:%s ,attrId2:%s ", channelType, productId, departDate, userId, attrId1, attrId2));
            ScenicPriceDTO result = scenicReservationService.queryAllPrices(channelType, attrId1, productId, userId, departDate);
            log.info(String.format("调用景点门票服务获取价格值:%s", JSON.toJSONString(result)));
            if (null != result && result.getMoreTicket() > 0) {
                cost.setCostPrice(result.getMoney());
                cost.setStock(result.getMoreTicket());
                return cost;
            }
        } catch (Exception e) {
            log.error("调用景点门票服务获取价格发生异常:{}", e);
        }
        return cost;
    }

    /* @MethodName: 固定套票默认景点门票的价格
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/19 13:32
     **/
    public BigDecimal getDefaultScenicPrice(Long packageId, LocalDate queryDate, Long userId, Integer channelType) {
        BigDecimal bd = BigDecimal.ZERO;
        //获取默认的 景点门票产品
        SeasonFixedProductPackageScenic scenic = seasonFixedProductPackageScenicMapper.selectOne(
                new QueryWrapper<SeasonFixedProductPackageScenic>().lambda().
                        eq(SeasonFixedProductPackageScenic::getIsDefault, SeasonType.YES_DEFAULT.getCode()).
                        eq(SeasonFixedProductPackageScenic::getIsDeleted, IsDeletedCode.NO.getCode()).
                        eq(SeasonFixedProductPackageScenic::getPackageId, packageId)
        );
        if (null != scenic) {
            PackageProductCostDTO cost = getScenicProductPrice(scenic.getProductId(), queryDate, userId, channelType, null, null);
            if (cost != null) {
                bd = cost.getCostPrice();
            }
        }
        return bd;
    }

    @Override
    public List<SeasonFixedProductPackageScenicDTO> getScenicByPackageId(Long packageId, LocalDate queryDate, Long userId, Integer channelType) {
        List<SeasonFixedProductPackageScenic> resultList = seasonFixedProductPackageScenicMapper.selectList(
                new QueryWrapper<SeasonFixedProductPackageScenic>().lambda().
                        eq(SeasonFixedProductPackageScenic::getIsDeleted, IsDeletedCode.NO.getCode()).
                        eq(SeasonFixedProductPackageScenic::getPackageId, packageId)
        );
        List<SeasonFixedProductPackageScenicDTO> resultDtoList = new ArrayList<>();
        if (null != resultList && resultList.size() > 0) {
            for (SeasonFixedProductPackageScenic result : resultList) {
                SeasonFixedProductPackageScenicDTO resultDto = EntityUtil.copy(result, SeasonFixedProductPackageScenicDTO.class);
                PackageProductCostDTO cost = getScenicProductPrice(result.getProductId(), queryDate, userId, channelType, null, null);
                resultDto.setCost(cost.getCostPrice());
                resultDto.setStock(cost.getStock());
                resultDtoList.add(resultDto);
            }
        }
        return resultDtoList;
    }

    @Override
    public List<SeasonFixedProductPackageScenicDTO> getDefaultScenicData(Long packageId, LocalDate queryDate, Long userId, Integer channelType) {
        List<SeasonFixedProductPackageScenic> resultList = seasonFixedProductPackageScenicMapper.selectList(
                new QueryWrapper<SeasonFixedProductPackageScenic>().lambda().
                        eq(SeasonFixedProductPackageScenic::getIsDefault, SeasonType.YES_DEFAULT.getCode()).
                        eq(SeasonFixedProductPackageScenic::getIsDeleted, IsDeletedCode.NO.getCode()).
                        eq(SeasonFixedProductPackageScenic::getPackageId, packageId)
        );
        List<SeasonFixedProductPackageScenicDTO> resultDtoList = new ArrayList<>();
        if (null != resultList && resultList.size() > 0) {
            for (SeasonFixedProductPackageScenic result : resultList) {
                SeasonFixedProductPackageScenicDTO resultDto = EntityUtil.copy(result, SeasonFixedProductPackageScenicDTO.class);
                PackageProductCostDTO cost = getScenicProductPrice(result.getProductId(), queryDate, userId, channelType, null, null);
                resultDto.setCost(cost.getCostPrice());
                resultDto.setStock(cost.getStock());
                resultDtoList.add(resultDto);
            }
        }
        return resultDtoList;
    }

    /* @MethodName: 批量保存 景点门票产品信息
     * @Description: TODO
     * @Param: userId 用户id  productId 产品id packageId 打包id  scenicReqList 景点门票集合
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/9 18:27
     **/
    @Override
    public void batchScenicProduct(Long userId, Long packageId, List<SeasonFixedProductPackageScenicReq> scenicReqList) {
        LocalDateTime now = LocalDateTime.now();
        List<SeasonFixedProductPackageScenic> scenicList = scenicReqList.stream().map(
                scenicReq -> {
                    SeasonFixedProductPackageScenic scenic = EntityUtil.copy(scenicReq, SeasonFixedProductPackageScenic.class);
                    scenic.setCreateId(userId);
                    scenic.setPackageId(packageId);
                    scenic.setGmtCreate(now);
                    scenic.setId(IdWorker.getId());
                    scenic.setIsDeleted(IsDeletedCode.NO.getCode());
                    return scenic;
                }
        ).collect(Collectors.toList());

        seasonFixedProductPackageScenicMapper.insertBatchSomeColumn(scenicList);
    }

    /* @MethodName: 获取固定套票 景点门票信息
     * @Description: TODO
     * @Param: fixedSeasonId 固定套票id   packageId 产品打包id
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/11 13:40
     **/
    @Override
    public List<SeasonFixedProductPackageScenicDTO> getSeasonFixedProductScenicDtoList(Long packageId) {
        List<SeasonFixedProductPackageScenic> productPackageScenicList = getSeasonFixedProductScenicList(packageId);
        List<SeasonFixedProductPackageScenicDTO> list = new LinkedList<>();
        if (null != productPackageScenicList && productPackageScenicList.size() > 0) {
            list = productPackageScenicList.stream().map(
                    scenic -> {
                        SeasonFixedProductPackageScenicDTO ScenicDto = EntityUtil.copy(scenic, SeasonFixedProductPackageScenicDTO.class);
                        return ScenicDto;
                    }
            ).collect(Collectors.toList());
        }
        return list;
    }

    /* @MethodName: 删除原来的景点票产品
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/12 16:26
     **/
    @Override
    public void deletePreviousScenic(Long userId, Long packageId) {
        LocalDateTime now = LocalDateTime.now();
        UpdateWrapper<SeasonFixedProductPackageScenic> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("modified_id", userId);//修改人
        updateWrapper.set("is_deleted", IsDeletedCode.YES.getCode());//删除
        updateWrapper.set("gmt_modified", now);//修改时间
        updateWrapper.eq("package_id", packageId);
        seasonFixedProductPackageScenicMapper.update(null, updateWrapper);
    }


    /* @MethodName: 获取景点门票的成本差价
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/23 13:49
     **/
    @Override
    public List<SeasonFixedProductPackageScenicDTO> getScenicDifferencePrice(UpdatePackageProductReq req) {
        Long packageId = req.getPackageId();
        //多少人
        Integer num = req.getPassengerReqList().stream().mapToInt(passenger -> passenger.getPassengerNum()).sum();
        BigDecimal num1 = new BigDecimal(String.valueOf(num));
        LocalDate queryDate = req.getStartDate();
        List<SeasonFixedProductPackageScenicDTO> list = new LinkedList<>();
        SeasonFixedProductPackageScenicDTO defaultDto = getSeasonFixedDefaultProductScenic(packageId, queryDate, req.getPassengerReqList(), req.getUserId());
        list.add(defaultDto);
        BigDecimal flagCost = defaultDto.getCost();
        List<SeasonFixedProductPackageScenic> scenicList = getScenic(packageId, SeasonType.NO_DEFAULT.getCode());
        scenicList.stream().forEach(
                scenic -> {
                    Long scenicProductId = scenic.getProductId();
                    SeasonFixedProductPackageScenicDTO scenicDto = EntityUtil.copy(scenic, SeasonFixedProductPackageScenicDTO.class);
                    BigDecimal singleCost = getScenicProductPrice(scenicProductId, queryDate, req.getUserId(), 1, null, null).getCostPrice();
                    BigDecimal scenicCost = singleCost.multiply(num1);
                    scenicDto.setCost(scenicCost);
                    if (scenicCost.compareTo(BigDecimal.ZERO) == 0) {//表示没有库存
                        scenicDto.setPriceDifference("售罄");
                    } else {
                        scenicDto.setPriceDifference(String.valueOf(flagCost.subtract(scenicCost)));//减法
                    }
                    scenicDto.setSingleCost(singleCost);//单间单晚成本
                    list.add(scenicDto);
                });


        return list;
    }

    public SeasonFixedProductPackageScenicDTO getSeasonFixedDefaultProductScenic(Long packageId, LocalDate queryDate, List<PassengerReq> passengerReqList, Long userId) {
        SeasonFixedProductPackageScenic scenic = getScenic(packageId, SeasonType.YES_DEFAULT.getCode()).get(0);
        SeasonFixedProductPackageScenicDTO scenicDTO = EntityUtil.copy(scenic, SeasonFixedProductPackageScenicDTO.class);
        BigDecimal scenicCost = getScenicProductPrice(scenicDTO.getProductId(), queryDate, userId, 1, null, null).getCostPrice();
        //旅客类型集合
        Integer num = passengerReqList.stream().mapToInt(passenger -> passenger.getPassengerNum()).sum();
        BigDecimal num1 = new BigDecimal(String.valueOf(num));
        BigDecimal totalCost = scenicCost.multiply(num1);
        scenicDTO.setCost(totalCost);
        if (scenicCost.compareTo(BigDecimal.ZERO) == 0) {
            scenicDTO.setPriceDifference("售罄");
        } else {
            scenicDTO.setPriceDifference("0");
        }
        return scenicDTO;
    }


    /* @MethodName: 获取固定套票 景点门票信息
     * @Description: TODO
     * @Param: fixedSeasonId 固定套票id   packageId 产品打包id
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/11 13:40
     **/
    private List<SeasonFixedProductPackageScenic> getSeasonFixedProductScenicList(Long packageId) {
        QueryWrapper<SeasonFixedProductPackageScenic> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("package_id", packageId);
        queryWrapper.eq("is_deleted", IsDeletedCode.NO.getCode());
        return seasonFixedProductPackageScenicMapper.selectList(queryWrapper);
    }


    /* @MethodName: 获取景点门票信息
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/2 11:19
     **/
    private List<SeasonFixedProductPackageScenic> getScenic(Long packageId, Integer isDefault) {

        return seasonFixedProductPackageScenicMapper.selectList(
                new QueryWrapper<SeasonFixedProductPackageScenic>().lambda()
                        .eq(SeasonFixedProductPackageScenic::getIsDefault, IsDeletedCode.NO.getCode())
                        .eq(SeasonFixedProductPackageScenic::getPackageId, packageId)
                        .eq(SeasonFixedProductPackageScenic::getIsDefault, isDefault)
        );

    }
}
